package cn.wenhaha.app.job.core;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.db.Entity;
import cn.hutool.json.JSONUtil;
import cn.wenhaha.app.log.bean.LogMapping;
import cn.wenhaha.app.log.bean.ReportErrorType;
import cn.wenhaha.app.log.service.SyncLogService;
import cn.wenhaha.common.utils.spring.SpringUtils;
import cn.wenhaha.sync.core.*;

import java.io.Serializable;
import java.util.Arrays;
import java.util.List;

/**
 * 同步核心上下文封装类
 * --------
 *
 * @author ：wyndem
 * @Date ：Created in 2022-12-04 15:00
 */
public class DataSyncCore {

    private final Integer sourceId;
    private final String sourceObj;
    private final String code;
    private final LogMapping logMapping;
    private final DataSyncCoreContext coreContext;
    private SyncLogService logService;

    public DataSyncCore(DataSource dataSource,LogMapping logMapping) {
        this.coreContext = dataSource.getSyncCoreContext();
        this.sourceId = dataSource.getSourceId();
        this.sourceObj = dataSource.getSourceObj();
        this.code = dataSource.getCode();
        this.logMapping = logMapping;
        this.logService = SpringUtils.getBean(SyncLogService.class);
    }

    public Integer getSourceId() {
        return sourceId;
    }

    public String getSourceObj() {
        return sourceObj;
    }

    public String getCode() {
        return code;
    }

    /**
     * 查询：
     * 1. 待同步的数据
     * 2. 需要定制的关联关系
     */
    public List<Entity> query(List<Column> field, List<Query> query) {
        coreContext.beforeEvent(sourceId, sourceObj, code);

        try {
            return coreContext.query(field, query);
        }catch (Exception e){

            SyncErrorReport syncErrorReport = new SyncErrorReport(this.code,sourceObj,sourceId,null,e.getMessage(),e,null);
            logService.add(logMapping,CollUtil.toList(syncErrorReport), ReportErrorType.QUERY);
            return null;
        } finally {
            coreContext.afterEvent();
        }

    }


    /**
     * <p>
     *    是否支持查询类型
     * </p>
     * @Author: Wyndem
     * @DateTime: 2022-12-18 19:28
     */
    public  Boolean isEchoQuery(String type){
        coreContext.beforeEvent(sourceId, sourceObj, code);
        try {
            return coreContext.isEchoQuery(type);
        }finally {
            coreContext.afterEvent();
        }

    }



    /**
     * <p>
     * 回显 -> 自定义操作
     * </p>
     *
     * @param column 一个column代表着一个回写字段。一组是当前对象的所有回写
     * @Author: Wyndem
     * @DateTime: 2022-11-22 22:10
     */
    public Entity echoQuery(List<Column> column) {
        coreContext.beforeEvent(sourceId, sourceObj, code);

        try {
            return coreContext.echoQuery(column);
        }catch (Exception e){
            Entity entity = Entity.create();
            entity.put("需查询数据", column.toString());
            SyncErrorReport syncErrorReport = new SyncErrorReport(this.code,sourceObj,sourceId,null,e.getMessage(),e,entity);
            logService.add(logMapping,CollUtil.toList(syncErrorReport), ReportErrorType.ECHO);
            return null;
        }  finally {
            coreContext.afterEvent();
        }

    }


    /**
     * 上传数据：
     * 1. 新增
     * 2. 保存
     *
     * @param id   对于数据中id字段
     * @param data 数据
     */
    public List<SyncReport> upload(String id, List<Entity> data,ReportErrorType errorType) {
        coreContext.beforeEvent(sourceId, sourceObj, code);

        try {
            List<SyncReport> upload = coreContext.upload(id, data);
            logService.add(logMapping,upload, errorType);
            return  upload;
        }catch (Exception e){
            for (Entity entity : data){
                Serializable dataId = null;
                if (StrUtil.isNotEmpty(id) && entity.containsKey(id)){
                    dataId =StrUtil.utf8Str(entity.get(id));
                }
                SyncErrorReport syncErrorReport = new SyncErrorReport(this.code,sourceObj,sourceId,dataId,e.getMessage(),e,entity);
                logService.add(logMapping,CollUtil.toList(syncErrorReport), errorType);
            }
            return  null;
        }finally {
            coreContext.afterEvent();
        }
    }

    public List<SyncReport> upload(String id, List<Entity> data) {
      return  upload(id,data,ReportErrorType.UPLOAD);
    }
    public List<SyncReport> uploadWrite(String id, List<Entity> data) {
      return  upload(id,data,ReportErrorType.WRITE);
    }

}
